cmake_minimum_required(VERSION 3.13)
project(TGFX)

#set(CMAKE_VERBOSE_MAKEFILE ON)
include(./third_party/vendor_tools/vendor.cmake)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
cmake_policy(SET CMP0063 NEW)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)

# Options for building tgfx
option(TGFX_BUILD_SVG "Enable building the SVG module" OFF)
option(TGFX_BUILD_LAYERS "Enable building the layers module" OFF)
option(TGFX_BUILD_DRAWERS "Enable building the tgfx-drawers library for testing" OFF)
option(TGFX_USE_OPENGL "Use OpenGL as the GPU backend" ON)
option(TGFX_USE_QT "Enable building with the Qt framework." OFF)
option(TGFX_USE_SWIFTSHADER "Enable building with the SwiftShader library" OFF)
option(TGFX_USE_ANGLE "Enable building with the ANGLE library" OFF)
option(TGFX_USE_FASTER_BLUR "Enable a faster blur algorithm instead of the standard Gaussian blur" ON)

# When enabled, ImageBuffers created from web native codecs won’t be fully decoded right away.
# Instead, they will use promise-awaiting calls before generating textures, allowing multiple
# images to be decoded simultaneously. Avoid enabling this if your rendering process requires
# multiple flush() calls in a single frame, as it may cause screen tearing, where parts of the
# screen update while others do not.
option(TGFX_USE_ASYNC_PROMISE "Enable async promises for loading images on the web" OFF)

# EMSCRIPTEN_PTHREADS can be set by vendor tools for building the wasm-mt architecture.
if (NOT WEB OR EMSCRIPTEN_PTHREADS)
    option(TGFX_USE_THREADS "Enable support for multithreaded rendering" ON)
endif ()

if (APPLE OR (WEB AND NOT TGFX_USE_THREADS))
    option(TGFX_USE_FREETYPE "Use Freetype as the vector backend" OFF)
else ()
    option(TGFX_USE_FREETYPE "Use Freetype as the vector backend" ON)
endif ()

if (IOS OR WEB)
    option(TGFX_USE_WEBP_DECODE "Enable embedded WEBP decoding support" ON)
elseif (NOT ANDROID AND NOT OHOS)
    option(TGFX_USE_PNG_DECODE "Enable embedded PNG decoding support" ON)
    option(TGFX_USE_PNG_ENCODE "Enable embedded PNG encoding support" ON)
    option(TGFX_USE_JPEG_DECODE "Enable embedded JPEG decoding support" ON)
    option(TGFX_USE_JPEG_ENCODE "Enable embedded JPEG encoding support" ON)
    option(TGFX_USE_WEBP_DECODE "Enable embedded WEBP decoding support" ON)
    option(TGFX_USE_WEBP_ENCODE "Enable embedded WEBP encoding support" ON)
endif ()


if ($ENV{CLION_IDE})
    set(CLION_IDE ON)
else ()
    set(CLION_IDE OFF)
endif ()
get_directory_property(HasParent PARENT_DIRECTORY)
if (MACOS AND CLION_IDE AND NOT HasParent)
    # CLion project needs test targets.
    option(TGFX_BUILD_TESTS "Enable building tgfx test targets" ON)
endif ()

if (TGFX_BUILD_SVG)
    set(TGFX_USE_PNG_ENCODE ON)
    set(TGFX_USE_JPEG_DECODE ON)
endif ()

if (TGFX_BUILD_TESTS)
    set(TGFX_BUILD_SVG ON)
    set(TGFX_BUILD_DRAWERS ON)
    set(TGFX_USE_FREETYPE ON)
else ()
    set(TGFX_BUILD_TESTS OFF)
endif ()

if (TGFX_BUILD_DRAWERS)
    set(TGFX_BUILD_LAYERS ON)
endif ()

if (TGFX_USE_FREETYPE)
    # Freetype needs libpng
    set(TGFX_USE_PNG_DECODE ON)
endif ()

message("TGFX_BUILD_SVG: ${TGFX_BUILD_SVG}")
message("TGFX_BUILD_LAYERS: ${TGFX_BUILD_LAYERS}")
message("TGFX_USE_OPENGL: ${TGFX_USE_OPENGL}")
message("TGFX_USE_QT: ${TGFX_USE_QT}")
message("TGFX_USE_SWIFTSHADER: ${TGFX_USE_SWIFTSHADER}")
message("TGFX_USE_ANGLE: ${TGFX_USE_ANGLE}")
message("TGFX_USE_FASTER_BLUR: ${TGFX_USE_FASTER_BLUR}")
message("TGFX_USE_THREADS: ${TGFX_USE_THREADS}")
message("TGFX_USE_FREETYPE: ${TGFX_USE_FREETYPE}")
message("TGFX_USE_PNG_DECODE: ${TGFX_USE_PNG_DECODE}")
message("TGFX_USE_PNG_ENCODE: ${TGFX_USE_PNG_ENCODE}")
message("TGFX_USE_JPEG_DECODE: ${TGFX_USE_JPEG_DECODE}")
message("TGFX_USE_JPEG_ENCODE: ${TGFX_USE_JPEG_ENCODE}")
message("TGFX_USE_WEBP_DECODE: ${TGFX_USE_WEBP_DECODE}")
message("TGFX_USE_WEBP_ENCODE: ${TGFX_USE_WEBP_ENCODE}")
message("TGFX_BUILD_TESTS: ${TGFX_BUILD_TESTS}")
message("TGFX_USE_ASYNC_PROMISE: ${TGFX_USE_ASYNC_PROMISE}")

if (NOT CMAKE_OSX_DEPLOYMENT_TARGET)
    if (DEPLOYMENT_TARGET)
        set(CMAKE_OSX_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET})
    elseif (MACOS)
        if (CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
            set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0")
        else ()
            set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15")
        endif ()
    elseif (IOS)
        set(CMAKE_OSX_DEPLOYMENT_TARGET "9.0")
    endif ()
endif ()

# collects tgfx common files.
file(GLOB_RECURSE SRC_FILES
        src/core/filters/*.*
        src/core/images/*.*
        src/core/shaders/*.*
        src/core/shapes/*.*
        src/core/utils/*.*
        src/gpu/ops/*.*
        src/gpu/processors/*.*
        src/gpu/proxies/*.*
        src/gpu/tasks/*.*)
list(APPEND TGFX_FILES ${SRC_FILES})
file(GLOB PLATFORM_COMMON_FILES
        src/core/*.*
        src/gpu/*.*
        src/core/codecs/*.*
        src/core/vectors/*.*
        src/platform/*.*)
list(APPEND TGFX_FILES ${PLATFORM_COMMON_FILES})

if (TGFX_BUILD_SVG)
    file(GLOB_RECURSE SVG_FILES
            src/svg/*.*)
    list(APPEND TGFX_FILES ${SVG_FILES})
endif ()

if (TGFX_BUILD_LAYERS)
    file(GLOB_RECURSE LAYERS_FILES
            src/layers/*.*)
    list(APPEND TGFX_FILES ${LAYERS_FILES})
endif ()

if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    list(APPEND TGFX_COMPILE_OPTIONS -Werror -Wall -Wextra -Weffc++ -Wconversion -pedantic -Werror=return-type -Wno-unused-command-line-argument)
endif ()

if (MSVC)
    list(APPEND TGFX_COMPILE_OPTIONS "/utf-8")
    list(APPEND TGFX_COMPILE_OPTIONS /w44251 /w44275)
    list(APPEND TGFX_COMPILE_OPTIONS /W4)
    list(APPEND TGFX_DEFINES NOMINMAX _USE_MATH_DEFINES)
endif (MSVC)

# Sets flags
if (CMAKE_BUILD_TYPE MATCHES "Debug")
    list(APPEND TGFX_DEFINES DEBUG)
    #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -g -O1")
endif ()

if (TGFX_USE_QT)
    set(TGFX_USE_SWIFTSHADER OFF)
    set(TGFX_USE_ANGLE OFF)
elseif (TGFX_USE_SWIFTSHADER)
    set(TGFX_USE_ANGLE OFF)
endif ()

if (TGFX_USE_QT OR TGFX_USE_SWIFTSHADER OR TGFX_USE_ANGLE)
    set(TGFX_USE_OPENGL ON)
endif ()

if (TGFX_USE_PNG_DECODE)
    list(APPEND TGFX_DEFINES TGFX_USE_PNG_DECODE)
    set(TGFX_USE_PNG ON)
endif ()

if (TGFX_USE_PNG_ENCODE)
    list(APPEND TGFX_DEFINES TGFX_USE_PNG_ENCODE)
    set(TGFX_USE_PNG ON)
endif ()

if (TGFX_USE_JPEG_DECODE)
    list(APPEND TGFX_DEFINES TGFX_USE_JPEG_DECODE)
    set(TGFX_USE_JPEG ON)
endif ()

if (TGFX_USE_JPEG_ENCODE)
    list(APPEND TGFX_DEFINES TGFX_USE_JPEG_ENCODE)
    set(TGFX_USE_JPEG ON)
endif ()

if (TGFX_USE_WEBP_DECODE)
    list(APPEND TGFX_DEFINES TGFX_USE_WEBP_DECODE)
    set(TGFX_USE_WEBP ON)
endif ()

if (TGFX_USE_WEBP_ENCODE)
    list(APPEND TGFX_DEFINES TGFX_USE_WEBP_ENCODE)
    set(TGFX_USE_WEBP ON)
endif ()

if (TGFX_USE_JPEG)
    list(APPEND TGFX_STATIC_VENDORS libjpeg-turbo)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/core/codecs/jpeg/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
    list(APPEND TGFX_INCLUDES third_party/out/libjpeg-turbo/${INCLUDE_ENTRY})
endif ()

if (TGFX_USE_WEBP)
    list(APPEND TGFX_STATIC_VENDORS libwebp)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/core/codecs/webp/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
    list(APPEND TGFX_INCLUDES third_party/libwebp/src)
endif ()

if (TGFX_USE_PNG)
    set(TGFX_USE_ZLIB ON)
    list(APPEND TGFX_STATIC_VENDORS libpng)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/core/codecs/png/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
    list(APPEND TGFX_INCLUDES third_party/out/libpng/${INCLUDE_ENTRY})
endif ()

if (TGFX_USE_ZLIB)
    list(APPEND TGFX_STATIC_VENDORS zlib)
endif ()

if (TGFX_BUILD_SVG)
    # SVG and PDF exports require glyphs to be convertible back to Unicode.
    list(APPEND TGFX_DEFINES TGFX_USE_GLYPH_TO_UNICODE)
endif ()

if (TGFX_USE_FASTER_BLUR)
    list(FILTER TGFX_FILES EXCLUDE REGEX "src/(gpu/processors|core/filters)/.*GaussianBlur.*")
else ()
    list(FILTER TGFX_FILES EXCLUDE REGEX "src/(gpu/processors|core/filters)/.*DualBlur.*")
endif ()

if (TGFX_USE_ASYNC_PROMISE)
    list(APPEND TGFX_DEFINES TGFX_USE_ASYNC_PROMISE)
endif ()

if (TGFX_USE_THREADS)
    list(APPEND TGFX_DEFINES TGFX_USE_THREADS)
endif ()

if (TGFX_USE_FREETYPE)
    list(APPEND TGFX_DEFINES TGFX_USE_FREETYPE)
    list(APPEND TGFX_STATIC_VENDORS freetype)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/core/vectors/freetype/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
    list(APPEND TGFX_INCLUDES third_party/freetype/include)
elseif (WEB)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/core/vectors/web/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
elseif (APPLE)
    # Uses CoreGraphics instead.
    list(APPEND TGFX_DEFINES TGFX_USE_CORE_GRAPHICS)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/core/vectors/coregraphics/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
endif ()

if (TGFX_USE_OPENGL)
    file(GLOB GFX_PLATFORM_FILES src/gpu/opengl/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
    file(GLOB_RECURSE GFX_PROCESSOR_FILES src/gpu/opengl/processors/*.*)
    list(APPEND TGFX_FILES ${GFX_PROCESSOR_FILES})
elseif (ANDROID)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/gpu/vulkan/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
elseif (APPLE)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/gpu/metal/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
    find_library(Metal_LIBS Metal REQUIRED)
    list(APPEND TGFX_SHARED_LIBS ${Metal_LIBS})
endif ()

file(GLOB_RECURSE EGL_PLATFORM_FILES src/gpu/opengl/egl/*.*)

if (TGFX_USE_QT)
    set(CMAKE_AUTOMOC ON)
    # need to set the CMAKE_PREFIX_PATH to local QT installation path, for example :
    # set(CMAKE_PREFIX_PATH /Users/username/Qt/6.6.1/macos/lib/cmake)
    find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
    find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets OpenGL Quick)
    list(APPEND TGFX_SHARED_LIBS Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::OpenGL
            Qt${QT_VERSION_MAJOR}::Quick)

    file(GLOB_RECURSE GPU_PLATFORM_FILES src/gpu/opengl/qt/*.*)
    list(APPEND TGFX_FILES ${GPU_PLATFORM_FILES})
    if (MACOS)
        file(GLOB CGL_PLATFORM_FILES src/gpu/opengl/cgl/CGLHardwareTexture.mm)
        list(APPEND TGFX_FILES ${CGL_PLATFORM_FILES})
        list(APPEND TGFX_DEFINES GL_SILENCE_DEPRECATION)
        find_library(OpenGL_LIBS OpenGL REQUIRED)
        list(APPEND TGFX_SHARED_LIBS ${OpenGL_LIBS})
    endif ()
elseif (TGFX_USE_SWIFTSHADER)
    list(APPEND TGFX_INCLUDES vendor/swiftshader/include)
    file(GLOB SWIFTSHADER_LIBS vendor/swiftshader/${LIBRARY_ENTRY}/*${CMAKE_SHARED_LIBRARY_SUFFIX})
    list(APPEND TGFX_SHARED_LIBS ${SWIFTSHADER_LIBS})
    list(APPEND TGFX_FILES ${EGL_PLATFORM_FILES})
elseif (TGFX_USE_ANGLE)
    file(GLOB ANGLE_LIBS vendor/angle/${PLATFORM}/${ARCH}/*${CMAKE_STATIC_LIBRARY_SUFFIX})
    list(APPEND TGFX_STATIC_LIBS ${ANGLE_LIBS})
    list(APPEND TGFX_INCLUDES vendor/angle/include)
    file(GLOB_RECURSE GPU_PLATFORM_FILES src/gpu/opengl/egl/*.*)
    list(APPEND TGFX_FILES ${GPU_PLATFORM_FILES})
else ()
    set(TGFX_USE_NATIVE_GL ON)
endif ()


list(APPEND TGFX_STATIC_VENDORS pathkit)
list(APPEND TGFX_INCLUDES third_party/pathkit)
list(APPEND TGFX_STATIC_VENDORS skcms)
list(APPEND TGFX_INCLUDES third_party/skcms)
if (TGFX_BUILD_SVG)
    list(APPEND TGFX_STATIC_VENDORS expat)
    list(APPEND TGFX_INCLUDES third_party/expat)
endif ()

if (WEB)
    file(GLOB_RECURSE PLATFORM_FILES src/platform/web/*.*)
    list(APPEND TGFX_FILES ${PLATFORM_FILES})
    list(APPEND TGFX_DEFINES TGFX_BUILD_FOR_WEB)
    if (TGFX_USE_NATIVE_GL)
        file(GLOB_RECURSE GPU_PLATFORM_FILES src/gpu/opengl/webgl/*.*)
        list(APPEND TGFX_FILES ${GPU_PLATFORM_FILES})
    endif ()
    list(APPEND TGFX_COMPILE_OPTIONS -fno-rtti -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0)
elseif (OHOS)
    find_library(PIXELMAP_NDK_LIB pixelmap_ndk.z)
    find_library(IMAGE_SOURCE_NDK_LIB image_source_ndk.z)
    find_library(PIXELMAP_LIB pixelmap)
    find_library(IMAGE_SOURCE_LIB image_source)
    find_library(ACE_NDK_LIB ace_ndk.z)
    find_library(HILOG_NDK_LIB hilog_ndk.z)
    find_library(ACE_NAPI_LIB ace_napi.z)
    find_library(NATIVE_BUFFER_LIB native_buffer)
    find_library(NATIVE_WINDOW_LIB native_window)
    list(APPEND TGFX_SHARED_LIBS ${PIXELMAP_NDK_LIB} ${IMAGE_SOURCE_NDK_LIB} ${PIXELMAP_LIB}
            ${IMAGE_SOURCE_LIB} ${ACE_NDK_LIB} ${HILOG_NDK_LIB} ${ACE_NAPI_LIB} ${NATIVE_BUFFER_LIB}
            ${NATIVE_WINDOW_LIB})
    file(GLOB_RECURSE PLATFORM_FILES src/platform/ohos/*.*)
    list(APPEND TGFX_FILES ${PLATFORM_FILES})
    if (TGFX_USE_NATIVE_GL)
        find_library(EGL_LIB EGL)
        find_library(GLES_LIB GLESv3)
        list(APPEND TGFX_SHARED_LIBS ${EGL_LIB} ${GLES_LIB})
        file(GLOB_RECURSE GPU_PLATFORM_FILES src/gpu/opengl/egl/*.*)
        list(APPEND TGFX_FILES ${GPU_PLATFORM_FILES})
    endif ()
elseif (IOS)
    # finds all required platform libraries.
    find_library(UIKit_LIBS UIKit REQUIRED)
    list(APPEND TGFX_SHARED_LIBS ${UIKit_LIBS})
    find_library(Foundation_LIBS Foundation REQUIRED)
    list(APPEND TGFX_SHARED_LIBS ${Foundation_LIBS})
    find_library(QuartzCore_LIBS QuartzCore REQUIRED)
    list(APPEND TGFX_SHARED_LIBS ${QuartzCore_LIBS})
    find_library(CoreGraphics_LIBS CoreGraphics REQUIRED)
    list(APPEND TGFX_SHARED_LIBS ${CoreGraphics_LIBS})
    find_library(CoreText_LIBS CoreText REQUIRED)
    list(APPEND TGFX_SHARED_LIBS ${CoreText_LIBS})
    find_library(CoreMedia_LIBS CoreMedia REQUIRED)
    list(APPEND TGFX_SHARED_LIBS ${CoreMedia_LIBS})
    find_library(ImageIO_LIBS ImageIO REQUIRED)
    list(APPEND TGFX_SHARED_LIBS ${ImageIO_LIBS})
    find_library(CORE_VIDEO CoreVideo)
    list(APPEND TGFX_SHARED_LIBS ${CORE_VIDEO})
    find_library(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2 c)
    list(APPEND TGFX_SHARED_LIBS ${ICONV_LIBRARIES})

    file(GLOB_RECURSE PLATFORM_FILES src/platform/apple/*.*)
    list(APPEND TGFX_FILES ${PLATFORM_FILES})

    if (TGFX_USE_NATIVE_GL)
        list(APPEND TGFX_DEFINES GLES_SILENCE_DEPRECATION)
        find_library(OpenGLES_LIBS OpenGLES REQUIRED)
        list(APPEND TGFX_SHARED_LIBS ${OpenGLES_LIBS})
        file(GLOB_RECURSE GPU_PLATFORM_FILES src/gpu/opengl/eagl/*.*)
        list(APPEND TGFX_FILES ${GPU_PLATFORM_FILES})
    endif ()
elseif (MACOS)
    # finds all required platform libraries.
    find_library(APPLICATION_SERVICES_FRAMEWORK ApplicationServices REQUIRED)
    list(APPEND TGFX_SHARED_LIBS ${APPLICATION_SERVICES_FRAMEWORK})
    find_library(QUARTZ_CORE QuartzCore REQUIRED)
    list(APPEND TGFX_SHARED_LIBS ${QUARTZ_CORE})
    find_library(COCOA Cocoa REQUIRED)
    list(APPEND TGFX_SHARED_LIBS ${COCOA})
    find_library(FOUNDATION Foundation REQUIRED)
    list(APPEND TGFX_SHARED_LIBS ${FOUNDATION})
    find_library(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2 c)
    list(APPEND TGFX_SHARED_LIBS ${ICONV_LIBRARIES})
    find_library(CORE_MEDIA CoreMedia)
    list(APPEND TGFX_SHARED_LIBS ${CORE_MEDIA})

    file(GLOB_RECURSE PLATFORM_FILES src/platform/apple/*.*)
    list(APPEND TGFX_FILES ${PLATFORM_FILES})

    if (TGFX_USE_NATIVE_GL)
        list(APPEND TGFX_DEFINES GL_SILENCE_DEPRECATION)
        find_library(OpenGL_LIBS OpenGL REQUIRED)
        list(APPEND TGFX_SHARED_LIBS ${OpenGL_LIBS})
        file(GLOB_RECURSE GPU_PLATFORM_FILES src/gpu/opengl/cgl/*.*)
        list(APPEND TGFX_FILES ${GPU_PLATFORM_FILES})
    endif ()

elseif (ANDROID)

    find_library(LOG_LIB log)
    list(APPEND TGFX_SHARED_LIBS ${LOG_LIB})
    find_library(ANDROID_LIB android)
    list(APPEND TGFX_SHARED_LIBS ${ANDROID_LIB})
    find_library(JNIGRAPHICS_LIB jnigraphics)
    list(APPEND TGFX_SHARED_LIBS ${JNIGRAPHICS_LIB})

    file(GLOB_RECURSE PLATFORM_FILES src/platform/android/*.*)
    list(APPEND TGFX_FILES ${PLATFORM_FILES})

    if (TGFX_USE_NATIVE_GL)
        find_library(GLESV2_LIB GLESv2)
        list(APPEND TGFX_SHARED_LIBS ${GLESV2_LIB})
        find_library(EGL_LIB EGL)
        list(APPEND TGFX_SHARED_LIBS ${EGL_LIB})
        file(GLOB_RECURSE GPU_PLATFORM_FILES src/gpu/opengl/egl/*.*)
        list(APPEND TGFX_FILES ${GPU_PLATFORM_FILES})
    endif ()

    # optimizes the output size
    list(APPEND TGFX_COMPILE_OPTIONS -ffunction-sections -fdata-sections -Os -fno-exceptions -fno-rtti)

elseif (WIN32)
    find_library(Bcrypt_LIB Bcrypt)
    list(APPEND TGFX_STATIC_LIBS ${Bcrypt_LIB})
    find_library(ws2_32_LIB ws2_32)
    list(APPEND TGFX_STATIC_LIBS ${ws2_32_LIB})
    find_library(DWrite_LIB DWrite)
    list(APPEND TGFX_STATIC_LIBS ${DWrite_LIB})

    file(GLOB_RECURSE PLATFORM_FILES src/platform/mock/*.*)
    list(APPEND TGFX_FILES ${PLATFORM_FILES})

    if (TGFX_USE_NATIVE_GL)
        file(GLOB_RECURSE GPU_PLATFORM_FILES src/gpu/opengl/wgl/*.*)
        find_library(OPENGL_LIB opengl32)
        list(APPEND TGFX_STATIC_LIBS ${OPENGL_LIB})
        list(APPEND TGFX_FILES ${GPU_PLATFORM_FILES})
    endif ()
elseif (CMAKE_HOST_SYSTEM_NAME MATCHES "Linux")
    find_package(Threads)
    list(APPEND TGFX_SHARED_LIBS ${CMAKE_THREAD_LIBS_INIT})
    list(APPEND TGFX_SHARED_LIBS dl)
    list(APPEND TGFX_COMPILE_OPTIONS -fPIC -pthread)

    file(GLOB_RECURSE PLATFORM_FILES src/platform/mock/*.*)
    list(APPEND TGFX_FILES ${PLATFORM_FILES})

    if (TGFX_USE_NATIVE_GL)
        find_library(GLESV2_LIB GLESv2)
        list(APPEND TGFX_SHARED_LIBS ${GLESV2_LIB})
        find_library(EGL_LIB EGL)
        list(APPEND TGFX_SHARED_LIBS ${EGL_LIB})
        file(GLOB_RECURSE GPU_PLATFORM_FILES src/gpu/opengl/egl/*.*)
        list(APPEND TGFX_FILES ${GPU_PLATFORM_FILES})
    endif ()
endif ()

add_vendor_target(tgfx-vendor STATIC_VENDORS ${TGFX_STATIC_VENDORS} SHARED_VENDORS ${TGFX_SHARED_VENDORS})
find_vendor_libraries(tgfx-vendor STATIC TGFX_VENDOR_STATIC_LIBRARIES SHARED TGFX_VENDOR_SHARED_LIBRARIES)
list(APPEND TGFX_STATIC_LIBS ${TGFX_VENDOR_STATIC_LIBRARIES})
list(APPEND TGFX_SHARED_LIBS ${TGFX_VENDOR_SHARED_LIBRARIES})

if (HasParent)
    set(TGFX_STATIC_LIBS ${TGFX_STATIC_LIBS} PARENT_SCOPE)
    set(TGFX_SHARED_LIBS ${TGFX_SHARED_LIBS} PARENT_SCOPE)
endif ()

foreach (FILE_PATH ${TGFX_FILES})
    get_filename_component(FILE_NAME "${FILE_PATH}" NAME_WE)
    if (NOT FILE_NAME)
        list(APPEND TGFX_EXCLUDE_FILES ${FILE_PATH})
    endif ()
endforeach ()

if (TGFX_EXCLUDE_FILES)
    list(REMOVE_ITEM TGFX_FILES ${TGFX_EXCLUDE_FILES})
endif ()

add_library(tgfx STATIC ${TGFX_FILES})
add_dependencies(tgfx tgfx-vendor)
target_compile_definitions(tgfx PUBLIC ${TGFX_DEFINES})
target_compile_options(tgfx PUBLIC ${TGFX_COMPILE_OPTIONS})
target_include_directories(tgfx PUBLIC include PRIVATE src)
target_include_directories(tgfx SYSTEM PRIVATE ${TGFX_INCLUDES})
merge_libraries_into(tgfx ${TGFX_STATIC_LIBS})
target_link_libraries(tgfx ${TGFX_SHARED_LIBS})
set_target_properties(tgfx PROPERTIES PREFIX "")


if (TGFX_BUILD_DRAWERS)
    file(GLOB_RECURSE DRAWER_FILES drawers/src/*.*)
    add_library(tgfx-drawers STATIC ${DRAWER_FILES})
    target_compile_options(tgfx-drawers PUBLIC ${TGFX_COMPILE_OPTIONS})
    set_target_properties(tgfx-drawers PROPERTIES PREFIX "")
    target_compile_definitions(tgfx-drawers PUBLIC ${TGFX_DEFINES})
    target_compile_options(tgfx-drawers PUBLIC ${TGFX_COMPILE_OPTIONS})
    target_include_directories(tgfx-drawers PUBLIC drawers/include PRIVATE include drawers/src)
    target_link_libraries(tgfx-drawers)
endif ()

if (TGFX_BUILD_TESTS)
    execute_process(COMMAND git rev-parse --short HEAD OUTPUT_VARIABLE HEAD_COMMIT)
    file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/test/baseline/.cache/HEAD "${HEAD_COMMIT}")
    if (NOT TGFX_SKIP_BASELINE_CHECK)
        set(CacheVersionFile ${CMAKE_CURRENT_SOURCE_DIR}/test/baseline/.cache/version.json)
        if (EXISTS ${CacheVersionFile})
            execute_process(COMMAND git diff -G. --name-only origin/main:test/baseline/version.json ${CacheVersionFile} OUTPUT_VARIABLE HAS_DIFF)
        else ()
            set(HAS_DIFF ON)
        endif ()
        if (HAS_DIFF)
            message(WARNING "The local md5 cache is out of date! Please run the 'update_baseline.sh' to regenerate the cache.")
        endif ()
    endif ()

    file(GLOB_RECURSE TGFX_TEST_FILES test/src/*.*)
    list(APPEND TGFX_TEST_LIBS tgfx-drawers tgfx ${TGFX_SHARED_LIBS})
    list(APPEND TGFX_TEST_INCLUDES src test/src third_party/json/include)

    add_vendor_target(test-vendor STATIC_VENDORS harfbuzz googletest)
    find_vendor_libraries(test-vendor STATIC TEST_VENDOR_STATIC_LIBRARIES)
    list(APPEND TGFX_TEST_LIBS ${TEST_VENDOR_STATIC_LIBRARIES})
    list(APPEND TGFX_TEST_INCLUDES
            third_party/harfbuzz/src
            third_party/googletest/googletest
            third_party/googletest/googletest/include)

    list(APPEND TGFX_TEST_COMPILE_OPTIONS ${TGFX_COMPILE_OPTIONS} -fno-access-control)
    list(APPEND TGFX_TEST_DEFINES ${TGFX_DEFINES})

    foreach (FILE_PATH ${TGFX_TEST_FILES})
        get_filename_component(FILE_NAME "${FILE_PATH}" NAME_WE)
        if (NOT FILE_NAME)
            list(APPEND TGFX_TEST_EXCLUDE_FILES ${FILE_PATH})
        endif ()
    endforeach ()

    if (TGFX_TEST_EXCLUDE_FILES)
        list(REMOVE_ITEM TGFX_TEST_FILES ${TGFX_TEST_EXCLUDE_FILES})
    endif ()

    list(APPEND TGFX_BASELINE_DEFINES ${TGFX_TEST_DEFINES} UPDATE_BASELINE)
    if (NOT TGFX_SKIP_GENERATE_BASELINE_IMAGES)
        list(APPEND TGFX_BASELINE_DEFINES GENERATE_BASELINE_IMAGES)
    endif ()
    # used to update the local md5 data for baseline testing and generate baseline images to the
    # out/ directory. each image has a "_base" suffix.
    add_executable(UpdateBaseline ${TGFX_TEST_FILES})
    add_dependencies(UpdateBaseline test-vendor)
    target_include_directories(UpdateBaseline PUBLIC ${TGFX_TEST_INCLUDES})
    target_include_directories(UpdateBaseline SYSTEM PRIVATE ${TGFX_INCLUDES})
    target_compile_definitions(UpdateBaseline PUBLIC ${TGFX_BASELINE_DEFINES})
    target_compile_options(UpdateBaseline PUBLIC ${TGFX_TEST_COMPILE_OPTIONS})
    target_link_options(UpdateBaseline PUBLIC ${TGFX_TEST_LINK_OPTIONS})
    target_link_libraries(UpdateBaseline ${TGFX_TEST_LIBS})

    add_executable(TGFXUnitTest ${TGFX_TEST_FILES})
    add_dependencies(TGFXUnitTest test-vendor)
    target_include_directories(TGFXUnitTest PUBLIC ${TGFX_TEST_INCLUDES})
    target_include_directories(TGFXUnitTest SYSTEM PRIVATE ${TGFX_INCLUDES})
    target_compile_definitions(TGFXUnitTest PUBLIC ${TGFX_TEST_DEFINES} SKIP_FRAME_COMPARE)
    target_compile_options(TGFXUnitTest PUBLIC ${TGFX_TEST_COMPILE_OPTIONS})
    target_link_options(TGFXUnitTest PUBLIC ${TGFX_TEST_LINK_OPTIONS})
    target_link_libraries(TGFXUnitTest ${TGFX_TEST_LIBS})

    add_executable(TGFXFullTest ${TGFX_TEST_FILES})
    add_dependencies(TGFXFullTest test-vendor)
    target_compile_definitions(TGFXFullTest PUBLIC ${TGFX_TEST_DEFINES})
    target_compile_options(TGFXFullTest PUBLIC ${TGFX_TEST_COMPILE_OPTIONS})
    target_include_directories(TGFXFullTest PUBLIC ${TGFX_TEST_INCLUDES})
    target_include_directories(TGFXFullTest SYSTEM PRIVATE ${TGFX_INCLUDES})
    target_link_options(TGFXFullTest PUBLIC ${TGFX_TEST_LINK_OPTIONS})
    target_link_libraries(TGFXFullTest ${TGFX_TEST_LIBS})
endif ()
